using System;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using TXLooker.Common;
using TXLooker.Common.Core;

namespace TXLooker.WorkItemExtention.Core
{
    class WIServerProvider : WIObject
    {
        protected IServerProvider Source
        {
            get { return this.m_source; }
            private set
            {
                if (value == null) throw new ArgumentException();
                this.m_source = value;

                this.Folder = this.m_source.Folder;

                this.m_source.NewProjects += OnNewProjects;
                this.m_source.PreRemoveProjects += OnPreRemoveProjects;

                this.LoadProjects(this.m_source.Projects);
            }
        }
        private IServerProvider m_source = null;

        private WIServerProvider()
            : base(null)
        { }
        public WIServerProvider(IServerProvider source)
            : this()
        {
            this.Source = source;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public TeamFoundationServer GetServer()
        {
            return this.Source.Server;
        }
        /// <summary>
        /// Return Store contains last changes
        /// </summary>
        /// <returns></returns>
        public override WorkItemStore GetStore()
        {
            WorkItemStore store = null;

            try
            {
                store = (WorkItemStore)this.Source.Server.GetService(typeof(WorkItemStore));
            }
            catch (System.Exception ex)
            {
                Debug.WriteLine(ex.ToString());
                LogManager.WriteMessageToCustomLog("Error (GetStore) WIServerProvider " + ex.Message);
            }

            return store;
        }
        public Uri ServerUri
        {
            get { return this.Source.ServerUri; }
        }
        public string ServerName
        {
            get { return this.Source.ServerName; }
        }
        public override WIObjectType Type
        {
            get { return WIObjectType.Server; }
        }

        public IEnumerable<WIProjectProvider> Projects
        {
            get
            {
                lock (this.Childs)
                {
                    foreach (WIProjectProvider item in this.Childs.Values)
                        yield return item;
                }
            }
        }

        public override OlFolderView FolderView
        {
            get { throw new NotImplementedException(); }
            set { throw new NotImplementedException(); }
        }

        private void OnNewProjects(object sender, IEnumerable<IProjectProvider> items)
        {
            LoadProjects(items);
        }
        private void OnPreRemoveProjects(object sender, IEnumerable<IProjectProvider> items)
        {
            this.UnLoadProjects(items);
        }

        private void LoadProjects(IEnumerable<IProjectProvider> items)
        {
            try
            {
                List<WIObject> results = new List<WIObject>();

                lock (this.Childs)
                {
                    List<WIProjectSettings> slist = new List<WIProjectSettings>();

                    foreach (IProjectProvider item in items)
                    {
                        WIProjectProvider provider = new WIProjectProvider(this, item);
                        results.Add(provider);
                        this.Childs.Add(provider.ProjectUri, provider);

                        //save into configs
                        WIProjectSettings settings = WIAppGlobal.Configs.GetProjectSettings(provider.ProjectUri);

                        if (settings != null)
                        {
                            provider.Settings.Merge(settings);
                            settings = provider.Settings;
                        }
                        else
                        {
                            settings = provider.Settings;
                        }

                        slist.Clear();
                        slist.Add(settings);
                        WIAppGlobal.Configs.SetProjectSettings(slist);

                        //
                        try
                        {
                            provider.Update();
                        }
                        catch (System.Exception ex)
                        {
                            Debug.WriteLine(ex.ToString());
                        }
                    }
                }

                this.RaiseNewChildItems(results);
            }
            catch (System.Exception ex)
            {
                LogManager.WriteMessageToCustomLog("Error (LoadProjects) WIServerProvider " + ex.Message);

            }
        }
        private void UnLoadProjects(IEnumerable<Uri> uries)
        {
            try
            {
                Dictionary<Uri, WIObject> map = new Dictionary<Uri, WIObject>();

                //for settings remove from configs
                List<WIProjectSettings> settingsList = new List<WIProjectSettings>();

                lock (this.Childs)
                {
                    foreach (Uri uri in uries)
                    {
                        if (this.Childs.ContainsKey(uri))
                        {
                            WIProjectProvider provider = this.Childs[uri] as WIProjectProvider;
                            map.Add(uri, provider);

                            settingsList.Add(provider.Settings);
                        }
                    }
                }


                if (map.Values.Count != 0)
                {
                    try
                    {
                        this.RaisePreRemoveChildItems(map.Values);
                    }
                    catch (System.Exception ex)
                    {
                        Debug.WriteLine(ex.ToString());
                    }

                    lock (this.Childs)
                    {
                        foreach (Uri key in map.Keys)
                        {
                            try
                            {
                                this.Childs[key].Delete();
                            }
                            catch (System.Exception ex)
                            {
                                Debug.WriteLine(ex.ToString());
                            }

                            this.Childs.Remove(key);
                        }
                    }

                    //remove settings from configs
                    WIAppGlobal.Configs.RemoveProjectSettings(settingsList);
                }

            }
            catch (System.Exception ex)
            {
                LogManager.WriteMessageToCustomLog("Error (UnloadProjects) WIServerProvider " + ex.Message);
            }
        }
        private void UnLoadProjects(IEnumerable<IProjectProvider> items)
        {
            try
            {
                List<Uri> uries = new List<Uri>();

                foreach (IProjectProvider item in items)
                    uries.Add(item.ProjectUri);

                this.UnLoadProjects(uries);
            }
            catch (System.Exception ex)
            {
                LogManager.WriteMessageToCustomLog("Error (UnLoadProjects) WIServerProvider " + ex.Message);
            }
        }

        protected override void UpdateData()
        {
            try
            {
                this.Source.Update();

                IEnumerable<WIProjectSettings> prevState = WIAppGlobal.Configs.GetProjectSettingsList(this.ServerUri);
                List<WIProjectSettings> settingsList = new List<WIProjectSettings>(prevState);

                lock (this.Childs)
                {
                    foreach (WIProjectProvider item in this.Childs.Values)
                    {
                        item.Update();
                        settingsList.Remove(item.Settings);
                    }
                }

                if (settingsList.Count != 0)
                    WIAppGlobal.Configs.RemoveProjectSettings(settingsList);
            }
            catch (System.Exception ex)
            {
                LogManager.WriteMessageToCustomLog("Error (UpdateData) WIServerProvider " + ex.Message);
            }
        }
        public override void Delete()
        {
            this.Source.NewProjects -= new TFEventHandler<IEnumerable<IProjectProvider>>(OnNewProjects);
            this.Source.PreRemoveProjects -= new TFEventHandler<IEnumerable<IProjectProvider>>(OnPreRemoveProjects);
            base.Delete();
        }

        public override string FolderName
        {
            //!!!!we do not create folder! Folder is created yet before instance init!!!!
            get { return this.Folder.Name; }
        }

        public WIProjectProvider GetProjectProvider(Uri projectUri)
        {
            try
            {
                WIProjectProvider target = null;

                if (this.Childs.ContainsKey(projectUri))
                    target = (WIProjectProvider)this.Childs[projectUri];

                return target;
            }
            catch (System.Exception ex)
            {
                LogManager.WriteMessageToCustomLog("Error (GetProjectProvider) WIServerProvider " + ex.Message);
                return null;
            }
        }
    }
}

